home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000 #2
/
Ham Radio 2000 - Volume 2.iso
/
HAMV2
/
TCP_IP
/
TNOS230S
/
RAWCONS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-08-18
|
9KB
|
441 lines
#ifdef UNIX
/*
* A "raw console" session manager. This is sort of a high-speed version of
* "curses" --- but uses the current terminal type, instead of either a dumb
* terminal or ANSI X3.64 emulation. It's a little smarter than "dumb", but
* not much.
*/
/*lint -save -e10 -e19 -e36 -e18 -e652 -e659 */
#ifdef HAVE_NCURSES_H
#include <ncurses.h>
#else
#include <curses.h>
#endif
#undef FALSE
#undef TRUE
#include "global.h"
#include "hardware.h"
#include "proc.h"
/*lint -restore */
#undef tputs
#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: rawcons.c,v 1.18 1997/08/19 01:19:22 root Exp root $";
#endif
#ifdef SM_RAW
#include <term.h>
/*
* ought to share these... they're going to be identical between raw and curses
*/
struct keytrie
{
enum {KT_DEF, KT_TRIE, KT_TVAL, KT_VAL} kt_type; /* type of entry */
int kt_tval; /* if a TVAL, the timed-out value */
union
{
struct keytrie *ktu_trie; /* sub-trie */
#define kt_trie kt_u.ktu_trie
int ktu_val; /* value */
#define kt_val kt_u.ktu_val
} kt_u;
};
static struct termios old_tty, new_tty;
static int Suspense, infoed;
static struct keytrie *keys;
static TERMINAL *my_term;
static void
key_init(void)
{
int i;
keys = mallocw(256 * sizeof *keys);
for (i = 256; i--; )
{
keys[i].kt_type = KT_DEF;
keys[i].kt_val = i;
}
}
static void
key_add(const char *str, int val)
{
const char *old;
struct keytrie *t;
int c, i;
/*
* Follow the trie until we get to the right subtrie for the string, then
* add the value. If we hit a KT_DEF, expand the trie. If we hit a KT_VAL
* change it to a KT_TVAL, which times out as a KT_VAL but continues as a
* KT_TRIE. If given a value for a KT_TRIE, change it to a KT_TVAL.
*/
if (!str || !*str)
return; /* no key to define */
old = str;
t = keys;
while (str[1])
{
c = uchar(*str++);
if (t[c].kt_type != KT_TRIE)
{
if (t[c].kt_type == KT_DEF)
t[c].kt_type = KT_TRIE;
else
{
t[c].kt_type = KT_TVAL;
t[c].kt_tval = t[c].kt_val;
}
t[c].kt_trie = mallocw(256 * sizeof (struct keytrie));
for (i = 256; i--; )
{
t[c].kt_trie[i].kt_type = KT_DEF;
t[c].kt_trie[i].kt_val = i;
}
}
t = t[c].kt_trie;
}
c = uchar(*str);
if (t[c].kt_type == KT_TRIE)
{
t[c].kt_type = KT_TVAL;
t[c].kt_tval = val;
}
else if (t[c].kt_type == KT_DEF)
{
t[c].kt_type = KT_VAL;
t[c].kt_val = val;
}
}
static int
raw_init(const struct sessmgr_sw *sm)
{
extern int Numrows, Numcols;
if (infoed)
set_curterm(my_term);
else
{
/*
* By rights we should use curses' setup, but then it becomes harder
* to configure either out. Waste a little memory for now; it's not
* going to be much more than the size of the terminfo file, which
* is itself rarely more than 1.5K.
*/
setupterm(0, 1, 0);
my_term = cur_term;
/* load keytrie */
key_init();
key_add(key_down, DNARROW);
key_add(key_f1, -3);
key_add(key_f2, -4);
key_add(key_f3, -5);
key_add(key_f4, -6);
key_add(key_f5, -7);
key_add(key_f6, -8);
key_add(key_f7, -9);
key_add(key_f8, -10);
key_add(key_f9, -11);
key_add(key_f10, -2);
key_add(key_left, LTARROW);
key_add(key_right, RTARROW);
key_add(key_up, UPARROW);
key_add("\177", '\b'); /* so DEL behaves as BS */
infoed = 1;
}
if (tcgetattr(0, &old_tty) == -1)
return 0;
new_tty = old_tty;
new_tty.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHONL);
new_tty.c_cc[VMIN] = 1;
new_tty.c_cc[VTIME] = 0;
tcsetattr(0, TCSADRAIN, &new_tty);
Numrows = lines;
Numcols = columns;
putp(enter_ca_mode);
return 1;
}
static void
raw_end(const struct sessmgr_sw *sm)
{
if (!Suspense)
{
putp(exit_ca_mode);
tcsetattr(0, TCSADRAIN, &old_tty);
}
}
static void
raw_suspend(const struct sessmgr_sw *sm)
{
if (!Suspense++)
{
putp(exit_ca_mode);
fflush(stdout);
tcsetattr(0, TCSADRAIN, &old_tty);
}
}
static void
raw_resume(const struct sessmgr_sw *sm)
{
extern int Numrows, Numcols;
if (!--Suspense)
{
tcsetattr(0, TCSADRAIN, &new_tty);
set_curterm(my_term);
Numrows = lines;
Numcols = columns;
putp(enter_ca_mode);
}
}
static int
raw_swap(const struct sessmgr_sw *sm, void *old, void *new)
{
int c;
if (old && new)
{
c = (int) new - 1;
putp(clear_screen);
printf(">>> switching to session %d", c);
if (Sessions[c].name && *Sessions[c].name)
printf(": %s", Sessions[c].name);
else if (Sessions[c].proc->name && *Sessions[c].proc->name)
printf(" [%s]", Sessions[c].proc->name);
printf(" (%s)\n", Sestypes[Sessions[c].type]);
}
return 0; /* only the current session can do output */
}
static void
raw_putch(const struct sessmgr_sw *sm, void *dp, int c)
{
putchar(c);
}
static void
raw_clreol(const struct sessmgr_sw *sm, void *dp)
{
putp(clr_eol);
}
static void
raw_flush(const struct sessmgr_sw *sm, void *dp)
{
if (!Suspense)
fflush(stdout);
}
static void *
raw_create(const struct sessmgr_sw *sm, struct session *sp)
{
return (void *) (sp - Sessions + 1);
}
static void
raw_destroy(const struct sessmgr_sw *sm, void *dp)
{
}
static void
raw_clrscr(const struct sessmgr_sw *sm, void *dp)
{
putp(clear_screen);
}
static int
raw_wherex(const struct sessmgr_sw *sm, void *dp)
{
return -1;
}
static int
raw_wherey(const struct sessmgr_sw *sm, void *dp)
{
return -1;
}
static void
raw_window(const struct sessmgr_sw *sm, void *dp, int x1, int y1, int x2,
int y2)
{
}
static void
raw_gotoxy(const struct sessmgr_sw *sm, void *dp, int x, int y)
{
putp(tparm(cursor_address, y - 1, x - 1));
}
static void
raw_high(const struct sessmgr_sw *sm, void *dp)
{
vidattr(A_REVERSE);
}
static void
raw_norm(const struct sessmgr_sw *sm, void *dp)
{
vidattr(A_NORMAL);
}
static void
raw_bground (const struct sessmgr_sw *sm OPTIONAL, void *dp OPTIONAL, int c OPTIONAL)
{
}
static void
raw_fground (const struct sessmgr_sw *sm OPTIONAL, void *dp OPTIONAL, int c OPTIONAL)
{
}
static void
raw_txtattr (const struct sessmgr_sw *sm OPTIONAL, void *dp OPTIONAL, int c OPTIONAL)
{
}
static void
raw_refresh (const struct sessmgr_sw *sm OPTIONAL, void *dp OPTIONAL)
{
}
static void
raw_cursor(const struct sessmgr_sw *sm, void *dp, int c)
{
switch (c)
{
case _NOCURSOR:
putp(cursor_invisible);
break;
case _NORMALCURSOR:
putp(cursor_normal);
break;
case _SOLIDCURSOR:
putp(cursor_visible);
break;
}
}
/*
* Same as for curses... probably ought to share them
*/
static int
kbchar(int ir)
{
extern int Keyboard;
unsigned char ch;
int i;
if (ir)
kalarm(500);
do
{
if (kwait(&Keyboard) != 0 && ir)
return -1;
}
while ((i = read(0, &ch, 1)) == 0 || (i == -1 && errno == EWOULDBLOCK));
kalarm(0);
if (i < 0)
{
tputs("NOS PANIC: Lost keyboard\n");
where_outta_here(1, "kbchar");
}
return ch;
}
static int
raw_kbread(const struct sessmgr_sw *sm, void *dp)
{
static int ungets[10];
struct keytrie *t;
static int unget;
int ungetc[10];
int c, i, u;
i = 0;
u = 0;
if (unget > i)
c = ungets[i++];
else
c = kbchar(0);
ungetc[u++] = c;
t = keys;
while (t[c].kt_type == KT_TRIE || t[c].kt_type == KT_TVAL)
{
t = t[c].kt_trie;
if (unget > i)
c = ungets[i++];
else
c = kbchar(1);
if (c == -1)
break;
ungetc[u++] = c;
}
if (t[c].kt_type == KT_VAL)
{
u = 0;
c = t[c].kt_val;
}
else if (t[c].kt_type == KT_TVAL)
{
u = 0;
c = t[c].kt_tval;
}
while (i < unget)
ungetc[u++] = ungets[i++];
if (u)
{
c = ungetc[0];
for (i = u; i; i--)
ungets[i - 1] = ungetc[i];
unget = u - 1;
}
return c;
}
struct sessmgr_sw raw_sessmgr =
{
"raw",
SM_STDIO,
raw_init,
(char *(*)(const struct sessmgr_sw *, char *)) 0,
raw_create,
(char *(*)(const struct sessmgr_sw *, void *, char *)) 0,
raw_swap,
raw_putch,
raw_clreol,
raw_clrscr,
raw_wherex,
raw_wherey,
raw_window,
raw_gotoxy,
raw_high,
raw_norm,
raw_bground,
raw_fground,
raw_txtattr,
raw_refresh,
raw_cursor,
raw_kbread,
raw_destroy,
raw_flush,
raw_suspend,
raw_resume,
raw_end,
};
#endif
#endif /* UNIX */